<?php
//应用控制类
class cpApp
{
	
	public $module;//模块名称		
	public $action;//操作名称
	public $config=array();//配置信息

	//构造函数，配置参数
    public function __construct($config=array())
	{
		//网址构造配置
		$this->config['URL_REWRITE_ON']=isset($config['URL_REWRITE_ON'])?$config['URL_REWRITE_ON']:false;
		//是否开启重写，true开启重写,false关闭重写
		$this->config['URL_MODULE_DEPR']=isset($config['URL_MODULE_DEPR'])?$config['URL_MODULE_DEPR']:'/';//模块分隔符
		$this->config['URL_ACTION_DEPR']=isset($config['URL_ACTION_DEPR'])?$config['URL_ACTION_DEPR']:'-';//操作分隔符
		$this->config['URL_PARAM_DEPR']=isset($config['URL_PARAM_DEPR'])?$config['URL_PARAM_DEPR']:'-';//参数分隔符
		$this->config['URL_HTML_SUFFIX']=isset($config['URL_HTML_SUFFIX'])?$config['URL_HTML_SUFFIX']:'.html';
		//伪静态后缀设置，，例如 .html 
		
		//模块配置
		$this->config['MODULE_PATH']=isset($config['MODULE_PATH'])?$config['MODULE_PATH']:'./module/';//模块存放目录
		$this->config['MODULE_SUFFIX']=isset($config['MODULE_SUFFIX'])?$config['MODULE_SUFFIX']:'Mod.class.php';//模块后缀
		$this->config['MODULE_INIT']=isset($config['MODULE_INIT'])?$config['MODULE_INIT']:'init.php';//初始程序
		$this->config['MODULE_DEFAULT']=isset($config['MODULE_DEFAULT'])?$config['MODULE_DEFAULT']:'index';//默认模块
		$this->config['MODULE_EMPTY']=isset($config['MODULE_EMPTY'])?$config['MODULE_EMPTY']:'empty';//空模块		
		
		//操作配置
		$this->config['ACTION_DEFAULT']=isset($config['ACTION_DEFAULT'])?$config['ACTION_DEFAULT']:'index';//默认操作
		$this->config['ACTION_EMPTY']=isset($config['ACTION_EMPTY'])?$config['ACTION_EMPTY']:'_empty';//空操作
		
		//日志配置
		$config['LOG_ON']=isset($config['LOG_ON'])?$config['LOG_ON']:false;//是否开启出错信息保存到文件，true开启，false不开启
		$config['LOG_PATH']=isset($config['LOG_PATH'])?$config['LOG_PATH']:'./data/log/';//出错信息存放的目录，出错信息以天为单位存放
		define('CP_LOG_ON',$config['LOG_ON']);
		define('CP_LOG_PATH',$config['LOG_PATH']);

		//检查模块目录
		$this->checkDir();
	}
	
	//检查模块存放目录是否存在，不存在，则创建
	 private function checkDir()
    {		
		// 如果模块存放目录不存在或者不是目录，则创建目录
		if((!file_exists($this->config['MODULE_PATH']))||(!is_dir($this->config['MODULE_PATH']))) 
		{
			//创建模块目录
			if (!@mkdir($this->config['MODULE_PATH'],0755))
			 {
				$this->error($this->config['MODULE_PATH']."模块目录不存在，请手动创建...");
			 } 
		}
		
		if(substr($this->config['MODULE_PATH'], -1) != "/")    
		{
			$this->config['MODULE_PATH'] .= "/";
		}
     }
	
	//网址解析
    private function _parseUrl()
	{
		$script_name=$_SERVER["SCRIPT_NAME"];//获取当前文件的路径
		$url= $_SERVER["REQUEST_URI"];//获取完整的路径，不包含"?"之后的字符串
		
		//去除url包含的当前文件的路径信息
		if(@strpos($url,$script_name,0)!==false)
		{
			 $url=substr($url,strlen($script_name)+1);
		}
		else
		{
			$script_name=str_replace(basename($_SERVER["SCRIPT_NAME"]),'',$_SERVER["SCRIPT_NAME"]);
			if(@strpos($url,$script_name,0)!==false)
			{
			 $url=substr($url,strlen($script_name));
			}
		}
		//去除问号后面的查询字符串
		if(($pos=strrpos($url,'?'))>0)
		{
			$url=substr($url,0,$pos);
		}
		//去除后缀
		if(($pos=strrpos($url,$this->config['URL_HTML_SUFFIX']))>0)
		{
			$url=substr($url,0,$pos);
		}
		$flag=0;
		//获取模块名称
		if(($pos=@strpos($url,$this->config['URL_MODULE_DEPR'],1))>0)
		{
			$this->module=substr($url,0,$pos);//模块
			$url=substr($url,$pos+1);//除去模块名称，剩下的url字符串
			$flag=1;
		}
		else
		{	//如果找不到模块分隔符，以当前网址为模块名
			$this->module=$url;
		}
		
		//获取操作方法名称
		if(($pos=@strpos($url,$this->config['URL_ACTION_DEPR'],1))>0)
		{
			$this->action=substr($url,0,$pos);//模块
			$url=substr($url,$pos+1);
		}
		else
		{
			if($flag)
			{
				$this->action=$url;
			}
		}	
			
		//解析参数
		$param=explode($this->config['URL_PARAM_DEPR'],$url);
		$param_count=count($param);
		for($i=0; $i<$param_count;$i=$i+2)
		{			
			$_GET[$i]=$param[$i];
			if(isset($param[$i+1]))
			{
				$_GET[$param[$i]]=$param[$i+1];
				$_GET[$i+1]=$param[$i+1];
			}
		}	
		
		//在其他页面通过$_GET['_module']和$_GET['_action']获取得到当前的模块和操作名
		$this->module=empty($this->module)?$this->config['MODULE_DEFAULT']:$this->module;
		$this->action=empty($this->action)?$this->config['ACTION_DEFAULT']:$this->action;
		$_GET['_module']=$this->module;
		$_GET['_action']=$this->action;	

	}
		
	//常量定义
    private function _define()
	{					
		$root=str_replace(basename($_SERVER["SCRIPT_NAME"]),'',$_SERVER["SCRIPT_NAME"]);
		$root=substr($root,0,-1);//去掉最后的斜杠		
		$root='http://'.$_SERVER['HTTP_HOST'].$root;
		
		define('__ROOT__',$root);//当前入口所在的目录
		define('__PUBLIC__',$root.'/public');//当前入口所在的目录
		//如果开启了重写，则网址不包含入口文件，如index.php
		if($this->config['URL_REWRITE_ON'])
		{
			define('__APP__',__ROOT__);
		}
		else
		{
			define('__APP__',__ROOT__.'/'.basename($_SERVER["SCRIPT_NAME"]));//当前入口文件
		}
		
		define('__URL__',__APP__.'/'.$this->module);//当前模块
	}
	
	//执行模块
    public function run()
	{
		$this->_parseUrl();//解析模块和操作
		
		//如果存在初始程序，则先执行初始程序
		if(file_exists($this->config['MODULE_PATH'].$this->config['MODULE_INIT']))
		{
				require_once($this->config['MODULE_PATH'].$this->config['MODULE_INIT']);//加载初始程序
		}
		
		$this->_define();//常量定义
		
		//指定模块存在，则执行指定模块存在
		if($this->_checkModule($this->module))
		{
				$this->_execute($this->module);
		}
		else
		{ 
		
			if($this->_checkModule($this->config['MODULE_EMPTY']))//如果存在空模块，则执行空模块
			{
				$this->_execute($this->config['MODULE_EMPTY']);
			}
			else
			{
				$this->error($this->module."模块不存在");//指定模块和空模块都不存在，则显示出错信息。
			}
		}
		
		//如果存在回调函数cp_app_end，则在即将结束前，调用回调函数
		if(function_exists('cp_app_end'))
		{
			cp_app_end();
		}
	}
	
	//检查模块文件是否存在,存在则加载，并返回true，不存在返回false
	private function _checkModule($module)
	{
		if(file_exists($this->config['MODULE_PATH'].$module.$this->config['MODULE_SUFFIX']))
		{
			require_once($this->config['MODULE_PATH'].$module.$this->config['MODULE_SUFFIX']);//加载模块文件
			return true;
		}
		else
		{
			return false;
		}
	}
	
	//执行操作
    private function _execute($module)
	{
		$module_suffix=explode('.',$this->config['MODULE_SUFFIX'],2);	

		$classname=$module.$module_suffix[0];
		if(class_exists($classname))
		{
			$object=new $classname();
			//类和方法同名，直接返回，因为跟类同名的方法会当成构造函数，已经被调用，不需要再次调用
			if($classname==$this->action)
			{
				return true;
			}
			
			if(method_exists($object,$this->action))
			{
				call_user_func(array(&$object,$this->action));
				
			}
			else if(method_exists($object,$this->config['ACTION_EMPTY']))
			{
				call_user_func(array(&$object,$this->config['ACTION_EMPTY']));
			}
			else
			{
				$this->error($this->action."操作方法在".$module."模块中不存在");
			}
		}
		else
		{
			$this->error($classname."类不存在");
		}
	}

    //输出错误信息
	public function error($str)
	{
		require_once(dirname(__FILE__).'/cpError.class.php');
		cpError::show($str);
	}
}
?>